package com.lee.sshclient.plugin;

import android.util.Log;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;

import java.io.IOException;
import java.io.OutputStream;

/**
 * Created by le on 2016/2/15.
 */
public class ShellOutputStream extends OutputStream {
    private CallbackContext callbackContext;
    /**
     * 字符集
     */
    protected String charset;
    /**
     * 设定一行缓冲区
     */
    private byte[] buf;
    /**
     * 缓冲位置
     */
    private int pos;
    /**
     * 当前执行的命令
     */
    private String curCmd;
    /**
     * 响应的命令
     */
    private String responseCommand = "";
    private boolean lastWasCR;
    /**
     * 是否已过滤发送命令
     */
    private boolean filterSendCommand = true;

    public ShellOutputStream(CallbackContext callbackContext, String charset) {
        this.callbackContext = callbackContext;
        this.charset = charset;
        this.buf = new byte[1024];
        this.pos = 0;
    }

    /**
     * 添加执行命令
     * @param command
     */
    public boolean addCommand(String command) {
        if(! filterSendCommand) {
            // 需要等待上一条命令执行完
            return false;
        }
        curCmd = command;
        filterSendCommand = false;
        return true;
    }

    @Override
    public synchronized void write(byte[] buffer, int offset, int len) throws IOException {
        for(int i = 0; i < len; i ++) {
            write(buffer[offset + i]);
        }
    }

    @Override
    public synchronized void write(int oneByte) throws IOException {
        if (lastWasCR) {
            if (buf[pos] == '\n') {
                return ;
            }
            lastWasCR = false;
        } else {
            if (oneByte == '\n' || oneByte == '\r') {
                lastWasCR = (oneByte == '\r');
                flush();
            } else {
                if (pos + 1 >= buf.length) {
                    expansion();
                }
                buf[pos++] = (byte) oneByte;
            }
        }
    }

    private void expansion() {
        int len = buf.length;
        byte[] newCache = new byte[len + (len >> 1)];
        System.arraycopy(buf, 0, newCache, 0, len);
        buf = newCache;
    }

    @Override
    public synchronized void flush() throws IOException {
        if(pos == 0) {
            writerLineToClient("");
            return ;
        }
        String responseLine = new String(buf, 0, pos, charset); // 响应行
        pos = 0;    // 重置
        if(filterSendCommand) {
            writerLineToClient(responseLine);
            super.flush();
        } else {
            responseCommand += responseLine;
            String sendCommand = curCmd;
            if(sendCommand.equals(responseCommand)) {
                Log.i("filterResponseCommand", "过滤请求命令" + sendCommand + "成功");
                filterSendCommand = true;
                responseCommand = "";
            }
        }
    }

    @Override
    public void close() throws IOException {
        super.close();
    }

    void writerLineToClient(String line) {
        Log.i("writerLineToClient", line);
        PluginResult pluginResult = new PluginResult(PluginResult.Status.OK, line);
        pluginResult.setKeepCallback(true);
        callbackContext.sendPluginResult(pluginResult);
    }

}
